package main

import (
	"Go36/article48/common"
	"Go36/article48/common/op"
	"fmt"
	"os"
	"runtime"
	"runtime/pprof"
	"time"
)

// profileNames 代表概要信息名称的列表。
var profileNames = []string{
	"goroutine",
	"heap",
	"allocs",
	"threadcreate",
	"block",
	"mutex",
}

// profileOps 代表为了生成不同的概要信息而准备的负载函数的字典。
var profileOps = map[string]common.OpFunc{
	"goroutine":    op.BlockProfile,
	"heap":         op.MemProfile,
	"allocs":       op.MemProfile,
	"threadcreate": op.BlockProfile,
	"block":        op.BlockProfile,
	"mutex":        op.BlockProfile,
}

// debugOpts 代表debug参数的可选值列表。
var debugOpts = []int{
	0,
	1,
	2,
}

func main() {
	prepare()
	for _, name := range profileNames {
		for _, debug := range debugOpts {
			err := genProfile(name, debug)
			if err != nil {
				return
			}
			time.Sleep(time.Millisecond)
		}
	}
}

func genProfile(name string, debug int) error {
	fmt.Printf("Generate %s profile (debug: %d) ...\n", name, debug)
	filename := fmt.Sprintf("%s_%d.out", name, debug)
	f, err := os.Create(filename)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Create File Error: %v", err)
		return err
	}
	defer f.Close()

	if err = common.Execute(profileOps[name], 10); err != nil {
		fmt.Fprintf(os.Stderr, "execute error: %v (%s)\n", err, filename)
		return err
	}
	profile := pprof.Lookup(name)
	err = profile.WriteTo(f, debug)
	if err != nil {
		fmt.Fprintf(os.Stderr, "write error: %v (%s)\n", err, filename)
		return err
	}
	return nil
}

func prepare() {
	runtime.MemProfileRate = 8
	runtime.SetBlockProfileRate(2)
}
